<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2020/6/23
 * Time: 14:28
 */
namespace app\index\service;
use think\Exception;

/**
 *  Redis锁操作类
 *  Date:   2016-06-30
 *  Author: fdipzone
 *  Ver:    1.0
 *
 *  Func:
 *  public  lock    获取锁
 *  public  unlock  释放锁
 *  private connect 连接
 */
class RedisLock {

    private $_config = array(
        'host' => 'localhost',
        'port' => 6379,
        'index' => 0,
        'auth' => '',
        'timeout' => 1,
        'reserved' => NULL,
        'retry_interval' => 100,
    );
    private $_redis;


    /**
     * 初始化
     * RedisLock constructor.
     * @throws Exception
     */
    public function __construct(){
        $this->_redis = $this->connect();
    }

    /**
     * 获取锁
     * @param  String  $key    锁标识
     * @param  Int     $expire 锁过期时间
     * @return Boolean
     */
    public function lock($key, $expire=5){
        $is_lock = $this->_redis->setnx($key, time()+$expire);

        // 不能获取锁
        if(!$is_lock){
            // 判断锁是否过期
            $lock_time = $this->_redis->get($key);

            // 锁已过期，删除锁，重新获取
            if(time()>$lock_time){
                $this->unlock($key);
                $is_lock = $this->_redis->setnx($key, time()+$expire);
            }
        }

        return $is_lock? true : false;
    }

    /**
     * 释放锁
     * @param  String  $key 锁标识
     * @return Boolean
     */
    public function unlock($key){
        return $this->_redis->del($key);
    }

    /**
     * 创建redis链接
     * @return bool|\Redis
     * @throws Exception
     */
    private function connect(){
        try{
            $redis = new \Redis();
            $redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);
            if(empty($this->_config['auth'])){
                $redis->auth($this->_config['auth']);
            }
            $redis->select($this->_config['index']);
        }catch(\RedisException $e){
            throw new Exception($e->getMessage());
        }
        return $redis;
    }


    /**设置使用过的code，设定一个过期时间
     * @param $code
     * @param int $timeout
     * @return bool
     */
    public function setCode($code,$timeout=30){
        return $this->_redis->set($code,$code,$timeout);
    }


    /**
     * 获取code是否存在，如果不存在则是没有相同的取餐码
     * @param $code
     * @return bool|string
     */
    public function getCode($code){
        return $this->_redis->get($code);
    }


    /**
     * 支付成功,或者支付失败，回调删除code
     * @param $code
     * @return int
     */
    public function deletedCode($code){
        return $this->_redis->del($code);
    }

}
